/*
 * CVIC.h
 *
 *  Created on: 05-06-2013
 *      Author: Sucharinho
 */

#ifndef CVIC_H_
#define CVIC_H_

#include "lpc23xx.h"

#define IRQ_INTERRUPT_ROUTINE	__attribute__ ((interrupt("IRQ")))
#define FIQ_INTERRUPT_ROUTINE	__attribute__ ((interrupt("FIQ")))

#define FIQ_MASK					0x00000040
#define IRQ_MASK					0x00000080
#define INTERRUPT_SOURCE_PMASK		0xFFFFFFFD

class CVIC {
public:
	enum EIntSource {
		WDT = (1 << 0),
		ARM_CORE_0 = (1 << 2),
		ARM_CORE_1 = (1 << 3),
		TIMER0 = (1 << 4),
		TIMER1 = (1 << 5),
		UART0 = (1 << 6),
		UART1 = (1 << 7),
		PWM1 = (1 << 8),
		I2C0 = (1 << 9),
		SPI_SSP0 = (1 << 10),
		SSP1 = (1 << 11),
		PLL = (1 << 12),
		RTC = (1 << 13),
		EINT0 = (1 << 14),
		EINT1 = (1 << 15),
		EINT2 = (1 << 16),
		EINT3 = (1 << 17),
		AD0 = (1 << 18),
		I2C1 = (1 << 19),
		BOD = (1 << 20),
		ETHERNET = (1 << 21),
		USB = (1 << 22),
		CAN1_2 = (1 << 23),
		SD_MMC = (1 << 24),
		GPDMA = (1 << 25),
		TIMER2 = (1 << 26),
		TIMER3 = (1 << 27),
		UART2 = (1 << 28),
		UART3 = (1 << 29),
		I2C2 = (1 << 30),
		I2S = (1 << 31)
	};

	enum EPriority {
		PRIO_1,
		PRIO_2,
		PRIO_3,
		PRIO_4,
		PRIO_5,
		PRIO_6,
		PRIO_7,
		PRIO_8,
		PRIO_9,
		PRIO_10,
		PRIO_11,
		PRIO_12,
		PRIO_13,
		PRIO_14,
		PRIO_15,
		PRIO_16
	};

	static void EnableIRQ(void);
	static void DisableIRQ(void);
	static void EnableFIQ(void);
	static void DisableFIQ(void);
	static void InitFIQ(EIntSource source);
	static void InitVectoredIRQ(EIntSource source, EPriority priority,
			void (*function)(void));
	static void EnableInterrupts(unsigned int interrupts) {
		VICIntEnable = interrupts & INTERRUPT_SOURCE_PMASK;
	}
	static void DisableInterrupts(unsigned int interrupts) {
		VICIntEnClr = interrupts  & INTERRUPT_SOURCE_PMASK;
	}
	static void FinishVectoredIRQ(void) {
		VICVectAddr = 0;
	}

private:
	static unsigned int GetCPSR(void);
	static void SetCPSR(unsigned int value);

};

inline unsigned int CVIC::GetCPSR(void) {
	unsigned int retval;
	asm volatile (" mrs  %0, cpsr" : "=r" (retval) : );
	return retval;
}

inline void CVIC::SetCPSR(unsigned int value) {
	asm volatile (" msr  cpsr, %0" : /* no outputs */: "r" (value) );
}

inline void CVIC::EnableIRQ(void) {
	unsigned int cpsr;
	cpsr = GetCPSR();
	SetCPSR(cpsr & ~IRQ_MASK);
}

inline void CVIC::DisableIRQ(void) {
	unsigned int cpsr;
	cpsr = GetCPSR();
	SetCPSR(cpsr | IRQ_MASK);
}

inline void CVIC::EnableFIQ(void) {
	unsigned int cpsr;
	cpsr = GetCPSR();
	SetCPSR(cpsr & ~FIQ_MASK);
}

inline void CVIC::DisableFIQ(void) {
	unsigned int cpsr;
	cpsr = GetCPSR();
	SetCPSR(cpsr | FIQ_MASK);
}

#undef FIQ_MASK
#undef IRQ_MASK
#undef INTERRUPT_SOURCE_PMASK

#endif /*CVIC_H_*/
